<?php

namespace App\JsonRPC;

use JsonException;
use Psr\Http\Message\ServerRequestInterface;
use Yiisoft\Arrays\ArrayHelper;
use Yiisoft\Json\Json;

class Request
{

    /**
     * @var string JSONRPC协议版本号，一般固定使用2.0
     */
    protected string $jsonrpc = '2.0';

    /**
     * @return string
     */
    public function getJsonrpc(): string
    {
        return $this->jsonrpc;
    }

    /**
     * @param string $jsonrpc
     */
    public function setJsonrpc(string $jsonrpc): void
    {
        $this->jsonrpc = $jsonrpc;
    }

    /**
     * @var string 请求唯一ID
     */
    protected string $id = '';

    /**
     * @return string
     */
    public function getId(): string
    {
        return $this->id;
    }

    /**
     * @param string $id
     */
    public function setId(string $id): void
    {
        $this->id = $id;
    }

    /**
     * @var string 请求方法
     */
    protected string $method;

    /**
     * @return string
     */
    public function getMethod(): string
    {
        return $this->method;
    }

    /**
     * @param string $method
     */
    public function setMethod(string $method): void
    {
        $this->method = $method;
    }

    /**
     * @var array 请求参数
     */
    protected array $params = [];

    /**
     * @return array
     */
    public function getParams(): array
    {
        return $this->params;
    }

    /**
     * @param array $params
     */
    public function setParams(array $params): void
    {
        $this->params = $params;
    }

    /**
     * @return bool 是否是提示
     */
    public function isNotification(): bool
    {
        return empty($this->getId());
    }

    public static function createFromArray(array $payload): self
    {
        $request = new self;
        $request->setId(ArrayHelper::getValue($payload, 'id', ''));
        $request->setMethod(ArrayHelper::getValue($payload, 'method', ''));
        $request->setParams(ArrayHelper::getValue($payload, 'params', []));
        if (empty($request->getMethod())) {
            throw new InvalidPayloadException('method不能为空');
        }
        return $request;
    }

    public static function createFromServerRequest(ServerRequestInterface $request): self
    {
        $payload = $request->getBody()->getContents();
        if (empty($payload)) {
            $payload = $request->getParsedBody();
            if (empty($payload)) {
                throw new InvalidPayloadException('找不到Payload信息');
            }
        }

        if (is_string($payload)) {
            try {
                $payload = Json::decode($payload);
            } catch (JsonException $e) {
                // 解析JSON失败，可能是无效数据
                throw new InvalidPayloadException('Payload不合法');
            }
        }

        if (ArrayHelper::isAssociative($payload, true)) {
            return self::createFromArray($payload);
        }

        $len = count($payload);
        if ($len < 2) {
            throw new InvalidPayloadException('批量请求数量要大于等于2');
        }

        $requestStacks = [];
        foreach ($payload as $item) {
            $requestStacks[] = self::createFromArray($item);
        }
        $batchRequest = new BatchRequest;
        $batchRequest->setRequests($requestStacks);
        return $batchRequest;
    }
}
